! 2 dimension
program demo

    use, intrinsic :: iso_fortran_env, only: rk => real64
    use ntree_factory_m, only: ntree_t, shape_t, make_boundary, make_ntree, make_range, point_t
    use queue_m, only: queue_t
    implicit none
    class(shape_t), allocatable :: boundary, range
    type (queue_t) :: found
    class(*), allocatable :: data
    type (ntree_t) :: quad_tree
    logical :: info
    integer :: i

    call make_boundary([0.0_rk, 0.0_rk], [1.0_rk, 1.0_rk], boundary=boundary, squared=.true.)
    call make_ntree(boundary, 2, quad_tree)
    call quad_tree%insert(point_t([0.5_rk, 0.5_rk], 1), info)
    call quad_tree%insert(point_t([-0.1_rk, 0.1_rk], 2), info)
    call quad_tree%insert(point_t([0.1_rk, 0.2_rk], 3), info)
    call quad_tree%insert(point_t([0.9_rk, 0.4_rk], 4), info)
    call quad_tree%insert(point_t([0.7_rk, 0.6_rk], 5), info)
    call quad_tree%insert(point_t([0.3_rk, 0.5_rk], 6), info)
    call quad_tree%insert(point_t([randu(), randu()], 7), info)
    call make_range([0.9_rk, 0.9_rk], 0.5_rk, range)
    call quad_tree%query(range, found)

    if (found%size() == 0) stop
    do i = 1, found%size()
        call found%dequeue(data)
        select type (data)
        type is (integer)
            print *, data
        end select
    end do

contains

    function randu() result(r)
        real :: r
        call random_number(r)
    end function randu

end program demo
